/**
 * Particle.java
 * Part of the Particle Physics Simulator
 * By Wilson Burhan and Tyler Simrell
 * Code based on code written by Matthew Alden
 * Version 1.0
 * Date Finished: 5/8/13
 */

import com.sun.j3d.utils.geometry.*;
import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;

/**
 * This class defines the behavior and attributes the of the particle.
 * @author Matthew Alden, modified by Tyler Simrell and Wilson Burhan
 */
public class Particle 
{
	public float mass;
	public Vector3f position;
	public Vector3f velocity;
	public Vector3f forceAccumulator;
	public BranchGroup BG;
	private TransformGroup TG;
	private Transform3D T3D;

	public Particle(float mass, float positionX, float positionY, float positionZ,  float velocityX, float velocityY, float velocityZ, float radius, Color3f color) {
		if (mass <= 0)
			throw new IllegalArgumentException();
		
		this.mass = mass;
		position = new Vector3f(positionX, positionY, positionZ);
		velocity = new Vector3f(velocityX, velocityY, velocityZ);
		forceAccumulator = new Vector3f();
		BG = new BranchGroup();
		BG.setCapability(BranchGroup.ALLOW_DETACH);
		TG = new TransformGroup();
		TG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		TG.addChild(createShape(radius, color));
		BG.addChild(TG);
		T3D = new Transform3D();
		updateTransformGroup();
	}
	
	public Particle(float mass, Tuple3f position, Tuple3f velocity, float radius, Color3f color) 
	{
		this(mass, position.x, position.y, position.z, velocity.x, velocity.y, velocity.z, radius, color);
	}
	
	/**
	 * This method updates the state of the particle.
	 * @param duration The duration between updates.
	 */
	public void updateState(float duration) 
	{
		// The force accumulator vector (net force) now becomes
		// the acceleration vector.
		forceAccumulator.scale(1 / mass);
		position.scaleAdd(duration, velocity, position);
		position.scaleAdd(duration * duration / 2, forceAccumulator, position);
		velocity.scaleAdd(duration, forceAccumulator, velocity);
	}

	/**
	 * This method updates the transform group so that the particle
	 * can move.
	 */
	public void updateTransformGroup() 
	{
		T3D.setTranslation(new Vector3f(position.x, position.y, position.z));
		TG.setTransform(T3D);
	}
	
	/**
	 * This method creates the shape of the particle. While this is a simulator
	 * for an infinitely small particle, it is represented by spheres.
	 * @param radius The size of the particles
	 * @param color The color of the particle
	 * @return The finished particle.
	 */
	private Node createShape(float radius, Color3f color) 
	{
		if (color == null)
			color = new Color3f(Color.getHSBColor((float)Math.random(), 1, 1));
		Appearance appearance = new Appearance();
		appearance.setColoringAttributes(new ColoringAttributes(color, ColoringAttributes.FASTEST));
		return new Sphere(radius, 0, 8, appearance);
	}
}
